# -*- coding: utf-8 -*-
import json
from collections import OrderedDict

import requests
from django.conf import settings

from async import async_job
from common.channel.base_pay import BasePay, SignMd5
from common.order.db import get_pay, add_pay_success
from common.utils import track_logging
from common.utils.exceptions import SignError

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    'c3dfbb796bc4538caff71ba8fb7ffb86': {
        'API_KEY': 'k5W1Fm1PCfdoezxA',
    },
    'gateway': 'https://www.bcucul.cn/api/shopApi/order/createorder',
    'query_gateway': 'https://www.bcucul.cn/api/shopApi/order/queryorder',
}

PAY_TYPE_DICT = {
    'cloud_flash': 'unionpay',  # 云闪付
    'alipay': 'alipay',  # 支付宝
    'wechat': 'wechat',  # 微信
}


class BaoZiPay(BasePay, SignMd5):

    @staticmethod
    def pending_str(parameter, key, key_name='key', allow='no', not_sign=[]):
        s = '%s%s%s%s%s' % (parameter['shop_id'], parameter['user_id'],
                            parameter['money'], parameter['type'], key)
        return s

    #  下单同步回调签名验证
    def create_back_sign(self, parameter, key, app_id):
        pending_str = '%s%s%s%s%s%s' % (app_id, parameter['user_id'],
                                        parameter['order_no'], key, parameter['type'], parameter['money'])
        sign = parameter['sign']
        calculated_sign = self.md5_sign(pending_str)
        if sign != calculated_sign:
            _LOGGER.info("baozipay sign: %s, calculated sign: %s", sign, calculated_sign)
            raise SignError('sign not pass, data: %s' % parameter)

    # 异步回调签名验证
    def verify_notify_sign(self, parameter, key, app_id):

        pending_str = '%s%s%s%s%s%s' % (app_id, parameter['user_id'],
                                        parameter['order_no'], key, parameter['money'], parameter['type'])
        sign = parameter['sign']
        calculated_sign = self.md5_sign(pending_str)
        if sign != calculated_sign:
            _LOGGER.info("baozipay sign: %s, calculated sign: %s", sign, calculated_sign)
            raise SignError('sign not pass, data: %s' % parameter)

    # 下单
    def create_charge(self, pay, pay_amount, info):
        app_id = info['app_id']
        service = info.get('service')
        api_key = self.get_api_key(APP_CONF, app_id)

        parameter_dict = OrderedDict((
            ('shop_id', app_id),  # 商户ID
            ('user_id', str(pay.id)),  # 商户用户id
            ('money', '%.2f' % (float(pay_amount))),  # 订单金额 元
            ('type', self.get_pay_type(service, PAY_TYPE_DICT)),  # 支付类型
            ('shop_no', str(pay.id)),  # 订单号
            ('notify_url', '{}/pay/api/{}/new/baozipay/{}'.format(
                settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
        ))
        # 待签名字符串
        pending_str = self.pending_str(parameter_dict, api_key)
        parameter_dict['sign'] = self.md5_sign(pending_str)

        json_parameter = json.dumps(parameter_dict)
        _LOGGER.info("baozipay create date: %s, order_id is: %s", json_parameter,
                     parameter_dict['shop_no'])

        headers = {'Content-Type': 'application/json'}
        response = requests.post(self.get_gateway(APP_CONF), data=json_parameter, headers=headers, timeout=10)
        data = json.loads(response.text)
        if response.status_code != 200:
            return {'charge_info': data['message']}
        self.create_back_sign(data, api_key, app_id)
        #  把渠道订单号存入数据库,查询需要使用渠道订单号
        trade_no = data['order_no']
        extend = {'trade_no': trade_no}
        pay = get_pay(pay.id)
        if pay:
            pay.extend = json.dumps(extend, ensure_ascii=False)
            pay.save()

        url = data['qrcode_url']
        _LOGGER.info('baozipay pay url: %s', url)
        return {'charge_info': url}

    # success异步回调
    def check_notify_sign(self, request, app_id):
        _LOGGER.info("baozipay notify body: %s", request.body)
        data = json.loads(request.body)
        _LOGGER.info("baozipay notify data: %s, order_id is: %s", data, data['shop_no'])
        self.verify_notify_sign(data, self.get_api_key(APP_CONF, app_id), app_id)
        pay_id = data['shop_no']
        pay = self.check_ip_pay_status(request, pay_id, channel_name='baozipay', data=data)
        if not pay:
            return 'success'  # 返回给渠道的信息

        mch_id = pay.mch_id
        trade_status = str(data['status'])
        trade_no = data['order_no']  # 平台订单号
        total_fee = float(data['money'])
        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee,
        }
        if trade_status == '0':
            self.check_channel_order(pay_id, total_fee, app_id)
            _LOGGER.info('baozipay check order success, user_id:%s pay_id:%s' % (mch_id, pay_id))
            add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
            # async notify
            async_job.notify_mch(pay_id)
            return 'success'

    # 订单查询
    def query_charge(self, pay_order, app_id):
        pay_id = pay_order.id
        api_key = self.get_api_key(APP_CONF, app_id)
        pay = get_pay(pay_id)
        parameter_dict = OrderedDict((
            ('shop_id', app_id),  # 商户ID
            ('order_no', str((json.loads(pay.extend)).get('trade_no'))),  # 平台订单号
        ))
        # 待签名字符串
        pending_str = '%s%s%s' % (parameter_dict['shop_id'], parameter_dict['order_no'], api_key)
        parameter_dict['sign'] = self.md5_sign(pending_str)

        json_parameter = json.dumps(parameter_dict)
        _LOGGER.info('baozipay query data %s, order_id is: %s', json_parameter,
                     pay.id)
        headers = {'Content-Type': 'application/json'}
        response = requests.post(self.get_query_geteway(APP_CONF), data=json_parameter, headers=headers, timeout=5)
        data = json.loads(response.text)
        _LOGGER.info('baozipay query rsp, %s', data)
        if response.status_code == 200:
            trade_status = data['status']
            total_fee = float(data.get('money'))
            trade_no = str(data['shop_no'])
            extend = {
                'trade_status': trade_status,
                'trade_no': trade_no,
                'total_fee': total_fee,
            }
            # 0表示支付成功；1表示等待支付；2表示支付超时；3表示支付失败；
            if trade_status == '0':
                self.check_channel_order(pay_id, total_fee, app_id)
                _LOGGER.info('baozipay query order success, mch_id:%s pay_id:%s' % (pay_order.mch_id, pay_id))
                add_pay_success(pay_order.mch_id, pay_id, total_fee, trade_no, extend)
                async_job.notify_mch(pay_order.id)
            else:
                _LOGGER.info('baozipay query order success,but not pay success,status:%s ' % data['status'])
        else:
            _LOGGER.warn('baozipay data error, msg: %s', data['message'])


def create_charge(pay, pay_amount, info):
    return BaoZiPay().create_charge(pay, pay_amount, info)


def check_notify_sign(request, app_id):
    return BaoZiPay().check_notify_sign(request, app_id)


def query_charge(pay_order, app_id):
    BaoZiPay().query_charge(pay_order, app_id)
